<!--
* @Name: TableComponent
* @Description: element-plus table 的公共组件
* @Author: 三咲问道
* @Date: 2025-07-06
-->
<template>
  <div class="TableComponent">
    <el-table :data="data.data" border style="width: 100%" @header-click="headerClick"
      @header-contextmenu="headerContextmenu" @cell-click="cellClick" @cell-dblclick="cellDblclick"
      @cell-contextmenu="cellContextmenu" @row-click="rowClick" @row-contextmenu="rowContextmenu"
      @row-dblclick="rowDblclick" @cell-mouse-enter="cellMouseEnter" @cell-mouse-leave="cellMouseLeave"
      @selection-change="selectionChange">

      <!--   序号列   -->
      <el-table-column v-if="showIndex" type="index" :width="indexWidth" :label="indexName" align="center" />

      <!--   多选   -->
      <el-table-column v-if="showSelection" type="selection" width="50" align="center" />

      <!--   是否单选   -->
      <el-table-column v-if="showRadio" width="35" align="center">
        <template v-slot="scope">
          <el-radio v-model="radioRow" :label="scope.row" @change="radioChange(scope.row)"></el-radio>
        </template>
      </el-table-column>

      <template v-for="(item, index) in columnList" :key="'c'+index">
        <el-table-column :label="item['columnName']" :width="item.width" :align="item.align || 'center'"
          :show-overflow-tooltip="item.overflow">
          <template #default="scope">

            <slot :name="item.slotName" :scope="scope">
              <div :class="{ 'link': item.isEvent, 't-o-e': item.overflow }">
                {{ scope.row[`${item.columnKey}`] }}
              </div>
            </slot>

          </template>
        </el-table-column>
      </template>
    </el-table>

    <div v-if="showPagination" class="pagination-content" :class="paginationDirection">
      <el-pagination :current-page="data.pageCurrent || pageCurrent" :page-size="data.pageSize || pageSize"
        :page-sizes="[10, 20, 30, 40, 50, 100]" background="background" layout="total, sizes, prev, pager, next, jumper"
        :total="data.total || total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </div>
  </div>
</template>


<script lang="ts" setup>
import { ref, toRefs } from "vue";

interface Column {
  columnKey: string, // 列的key
  columnName: string, // 列的 label（名字）
  width?: number | string, // 列的宽度
  isEvent?: boolean, // 该列是否是点击事件
  overflow?: boolean, // 该列是否超出 有tip 显示
  align?: string, // 列对齐
  slotName?: string
}

const props = defineProps({
  columnList: Array,
  data: Object || Array,
  showPagination: {
    type: Boolean,
    default: true
  }, // 是否显示分页
  paginationDirection: {
    type: String,
    default: 'p-d-r'
  }, // 分页方向 p-d-l p-d-c p-d-r
  current: {
    type: Number,
    default: 1
  },
  size: {
    type: Number,
    default: 10
  },
  total: {
    type: Number,
    default: 0
  },
  showIndex: Boolean, // 是否显示序号
  /**  序号列名称  */
  indexName: {
    type: String,
    default: '序号'
  },
  /**  序号列宽度  */
  indexWidth: {
    type: Number,
    default: 60
  },
  showSelection: Boolean, // 是否多选
  showRadio: Boolean, // 是否显示单选

})

const {
  columnList,
  data,
  showPagination,
  paginationDirection,
  current,
  size,
  total,
  showIndex,
  indexName,
  indexWidth,
  showSelection,
  showRadio,
} = toRefs(props)

let radioRow = ref({})

const emit = defineEmits(['header-click', 'size-change', 'current-change', 'header-contextmenu', 'cell-click', 'cell-dblclick',
  'cell-contextmenu', 'row-click', 'row-contextmenu', 'row-dblclick', 'cell-mouse-enter', 'cell-mouse-leave', 'selection-change', 'radio-change'])

const handleSizeChange = (e) => {
  emit('size-change', e)
}

const handleCurrentChange = (e) => {
  emit('current-change', e)
}

/**  当某一列的表头被点击时会触发该事件  */
const headerClick = (column, event) => {
  emit('header-click', column, event)
}

/**  当某一列的表头被鼠标右键点击时触发该事件  */
const headerContextmenu = (column, event) => {
  event.returnValue = false;
  emit('header-contextmenu', column, event)
}

const cellClick = (row, column, cell, event) => {
  emit('cell-click', row, column, cell, event)
}

const cellDblclick = (row, column, cell, event) => {
  emit('cell-dblclick', row, column, cell, event)
}

const cellContextmenu = (row, column, cell, event) => {
  emit('cell-contextmenu', row, column, cell, event)
}

const rowClick = (row, column, event) => {
  emit('row-click', row, column, event)
}

const rowContextmenu = (row, column, event) => {
  emit('row-contextmenu', row, column, event)
}

const rowDblclick = (row, column, event) => {
  emit('row-dblclick', row, column, event)
}

const cellMouseEnter = (row, column, cell, event) => {
  emit('cell-mouse-enter', row, column, cell, event)
}

const cellMouseLeave = (row, column, cell, event) => {
  emit('cell-mouse-leave', row, column, cell, event)
}

/**  当选择项发生变化时会触发该事件  */
const selectionChange = (selection) => {
  emit('selection-change', selection)
}

const radioChange = (row) => {
  radioRow.value = row
  emit('radio-change', row)
}


</script>

<style lang="less" scoped>
.TableComponent {

  :deep(thead tr:first-child th) {
    background: #f9f9f9;
  }

  .link {
    color: #409eff;
    cursor: pointer;
  }

  .t-o-e {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .t-l {
    text-align: left;
  }

  .pagination-content {
    margin-top: 14px;
  }

  .p-d-l {
    display: flex;
    justify-content: start;
  }

  .p-d-c {
    display: flex;
    justify-content: center;
  }

  .p-d-r {
    display: flex;
    justify-content: end;
  }
}
</style>